﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace LiteExpress.Utilities
{
    public class FormWebRequest: WebRequest
    {
        private NameValueCollection _form;
        private Encoding _encoding;
        private FormWebRequest() { }

        public static FormWebRequest GetInstance(string url, NameValueCollection form = null, string method = "get", Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            #region 设置url
            if (method.Equals("get", StringComparison.CurrentCultureIgnoreCase)
                && form != null)
            {
                StringBuilder urlbuilder = new StringBuilder();
                foreach (var key in form.AllKeys)
                {
                    if (urlbuilder.Length > 0)
                        urlbuilder.Append("&");
                    urlbuilder.AppendFormat("{0}={1}", HttpUtility.UrlEncode(key, encoding), HttpUtility.UrlEncode(form[key], encoding));
                }
                if (url.Contains("?"))
                {
                    url += "&" + urlbuilder.ToString();
                }
                else
                {
                    url += "?" + urlbuilder.ToString();
                }
                form = null;
            }
            #endregion
            var ret = WebRequest.Create(url) as FormWebRequest;
            ret.Method = method;
            ret._encoding = encoding;
            return ret;
        }
        public override WebResponse GetResponse()
        {
            #region initialize
            if (string.IsNullOrEmpty(this.ContentType))
            {
                this.ContentType = "application/x-www-form-urlencoded";
            }
            if (this.Timeout == 0)
            {
                this.Timeout = 5000;
            }
            #endregion

            #region 处理参数
            if (this._form != null)
            {
                string reqdata = string.Empty;

                StringBuilder reqdatabuilder = new StringBuilder();
                foreach (string key in this._form.AllKeys)
                {
                    if (reqdatabuilder.Length > 0)
                        reqdatabuilder.Append("&");
                    reqdatabuilder.AppendFormat("{0}={1}", HttpUtility.UrlEncode(key, this._encoding), HttpUtility.UrlEncode(this._form[key], this._encoding));
                }
                reqdata = reqdatabuilder.ToString();

                byte[] data = this._encoding.GetBytes(reqdata);

                using (Stream reqstream = this.GetRequestStream())
                {
                    reqstream.Write(data, 0, data.Length);
                    reqstream.Close();
                }
            }
            #endregion
            return base.GetResponse();
        }

        public string GetHtml()
        {
            string html = string.Empty;
            using (var res = this.GetResponse())
            {
                using (var stream = res.GetResponseStream())
                {
                    using (var sr = new StreamReader(stream))
                    {
                        html = sr.ReadToEnd();
                        sr.Close();
                    }
                    stream.Close();
                }
                res.Close();
            }
            return html;
        }
    }

    public class JsonWebRequest : WebRequest
    {
        private object _obj;
        private Encoding _encoding;
        private JsonWebRequest() { }

        public static JsonWebRequest GetInstance(string url,  object obj, string method = "get", Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
                       
            var ret = WebRequest.Create(url) as JsonWebRequest;
            ret.Method = method;
            ret._encoding = encoding;
            ret._obj = obj;
            return ret;
        }
        public override WebResponse GetResponse()
        {
            #region initialize
            if (string.IsNullOrEmpty(this.ContentType))
            {
                this.ContentType = "application/json";
            }
            if (this.Timeout == 0)
            {
                this.Timeout = 5000;
            }
            #endregion

            #region 处理参数
            if (this._obj != null)
            {
                string reqdata = string.Empty;
                reqdata = JsonConvert.SerializeObject(this._obj);

                byte[] data = this._encoding.GetBytes(reqdata);
                using (Stream reqstream = this.GetRequestStream())
                {
                    reqstream.Write(data, 0, data.Length);
                    reqstream.Close();
                }
            }
            #endregion
            return base.GetResponse();
        }
    }



    public class TestCase
    {
        private void TestFormRequest()
        {
            var req = FormWebRequest.GetInstance(
                url: "http://host/url",
                form: new NameValueCollection
                {
                    { "Key", "Value" }
                },
                method: "get",
                encoding: Encoding.UTF8);            
            req.Timeout = 60000;            
            using (var res = req.GetResponse())
            {
                using (var stream = res.GetResponseStream())
                {
                    using (var sr = new StreamReader(stream))
                    {
                        string html = sr.ReadToEnd();
                        sr.Close();
                    }
                    stream.Close();
                }
                res.Close();
            }
        }

        private void TestJsonRequest()
        {
            dynamic obj = new { fdsa = "fdsaf"};
            var req = JsonWebRequest.GetInstance(
                url:"http://host/url", 
                obj: obj,
                method:"post",
                encoding: Encoding.UTF8 
                );
            req.Timeout = 6000;
            using (var res = req.GetResponse())
            {
                var stream = res.GetResponseStream();
                
            }
        }
    }
    /// <summary>
    /// httpwebrequest帮助类
    /// </summary>    
    public static class HttpHelper
    {
        /// <summary>
        /// 发起http请求
        /// </summary>
        /// <example>HttpHelper.SendRequest("http://www.baidu.com", "get"
        ///         , new { appkey = appkey, accesstoken = access_token }
        ///         , (req) => { //请求之前对webrequest对象的修改，常用代码如下:
        ///             req.Accept = "application/json";
        ///             req.Referer = "http://referhost/url";
        ///             req.Headers.Add("headername", "headervalue");
        ///             req.MaximumAutomaticRedirections = 3;
        ///             req.Timeout = 5000; 
        ///         });
        /// </example>
        /// <param name="method">post或get</param>
        /// <param name="param">提交参数</param>
        /// <param name="reqFunc">请求之前对webrequest对象的修改</param>
        /// <param name="encoding">编码，默认为utf8</param>
        public static WebResponse SendFormRequest(string url, string method,            
            NameValueCollection param = null,
            Action<WebRequest> reqFunc = null,
            Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }

            #region 设置url
            if (method.Equals("get", StringComparison.CurrentCultureIgnoreCase)
                && param != null)
            {
                StringBuilder urlbuilder = new StringBuilder();
                foreach (var key in param.AllKeys)
                {
                    if (urlbuilder.Length > 0)
                        urlbuilder.Append("&");
                    urlbuilder.AppendFormat("{0}={1}", HttpUtility.UrlEncode(key, encoding), HttpUtility.UrlEncode(param[key], encoding));
                }
                if (url.Contains("?"))
                {
                    url += "&" + urlbuilder.ToString();
                }
                else
                {
                    url += "?" + urlbuilder.ToString();
                }
                param = null;
            }
            #endregion

            var req = WebRequest.Create(url) as HttpWebRequest;
            req.Method = method;
            req.ContentType = "application/x-www-form-urlencoded";
            req.MaximumAutomaticRedirections = 3;
            req.Timeout = 5000;

            if (reqFunc != null)
            {
                reqFunc(req);
            }
            

            #region 处理参数
            if (param != null)
            {
                string reqdata = string.Empty;

                StringBuilder reqdatabuilder = new StringBuilder();
                foreach (string key in param.AllKeys)
                {
                    if (reqdatabuilder.Length > 0)
                        reqdatabuilder.Append("&");
                    reqdatabuilder.AppendFormat("{0}={1}", HttpUtility.UrlEncode(key, encoding), HttpUtility.UrlEncode(param[key], encoding));
                }
                reqdata = reqdatabuilder.ToString();

                byte[] data = encoding.GetBytes(reqdata);

                using (Stream reqstream = req.GetRequestStream())
                {
                    reqstream.Write(data, 0, data.Length);
                    reqstream.Close();
                }
            }
            #endregion

            return req.GetResponse();
        }

        /// <summary>
        /// 提交json请求
        /// </summary>
        /// <param name="method">post或get</param>
        /// <param name="param">提交参数</param>
        /// <param name="reqSetFunc">请求之前对webrequest对象的修改</param>
        /// <param name="encoding">编码，默认为utf8</param>
        public static WebResponse SendJsonRequest<T>(string url, string method,
            T param, Action<WebRequest> reqFunc = null,
            Encoding encoding = null, Func<T, string> serializer = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = method;
            req.ContentType = "application/json";
            req.MaximumAutomaticRedirections = 3;
            req.Timeout = 5000;

            if (reqFunc != null)
            {
                reqFunc(req);
            }            

            #region 处理参数
            if (param != null)
            {
                string reqdata = string.Empty;
                if (serializer != null)
                {
                    reqdata = serializer(param);
                }
                else
                {
                    reqdata = JsonConvert.SerializeObject(param);
                }

                byte[] data = encoding.GetBytes(reqdata);
                using (Stream reqstream = req.GetRequestStream())
                {
                    reqstream.Write(data, 0, data.Length);
                    reqstream.Close();
                }
            }
            #endregion

            return req.GetResponse();
        }

        public static HttpStatusCode GetHttpCode(WebResponse response)
        {
            if (response == null)
            {
                return HttpStatusCode.BadRequest;
            }
            var webres = (System.Net.HttpWebResponse)response;
            return webres.StatusCode;
        }

        public static string GetHtml(WebResponse response, Encoding encoding = null)
        {
            if (response == null)
            {
                return string.Empty;
            }

            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }

            using (StreamReader reader = new StreamReader(response.GetResponseStream(), encoding))
            {
                return reader.ReadToEnd();
            }
        }
        
        public static string GetUrlFromParameters(NameValueCollection paramcollection, Encoding encoding = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }

            StringBuilder reqdatabuilder = new StringBuilder();
            foreach (string key in paramcollection.AllKeys)
            {
                if (reqdatabuilder.Length > 0)
                    reqdatabuilder.Append("&");
                reqdatabuilder.AppendFormat("{0}={1}", HttpUtility.UrlEncode(key, encoding), HttpUtility.UrlEncode(paramcollection[key], encoding));
            }
            return reqdatabuilder.ToString();
        }


    }
}
